home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / fontutil.6 / fontutil / fontutils-0.6 / limn / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-23  |  12.1 KB  |  342 lines

  1. /* limn -- convert bitmaps to splines.
  2.  
  3. Copyright (C) 1992 Free Software Foundation, Inc.
  4.  
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include "bzr.h"
  22. #include "cmdline.h"
  23. #include "font.h"
  24. #include "logreport.h"
  25. #include "getopt.h"
  26. #include "spline.h"
  27.  
  28. #include "display.h"
  29. #include "fit.h"
  30. #include "main.h"
  31. #include "output-bzr.h"
  32. #include "pxl-outline.h"
  33.  
  34.  
  35. /* The resolution of the font we will read, in pixels per inch.  We
  36.    don't deal with nonsquare pixels.  (-dpi)  */
  37. string dpi = "300";
  38.  
  39. /* Says which characters we should process.  This is independent of the
  40.    ordering in the font file.  (-range)  */
  41. int starting_char = 0;
  42. int ending_char = MAX_CHARCODE;
  43.  
  44. static string read_command_line (int, string []);
  45.  
  46. int
  47. main (int argc, string argv[])
  48. {
  49.   int code;
  50.   string font_name = read_command_line (argc, argv);
  51.   bitmap_font_type f = get_bitmap_font (font_name, atou (dpi));
  52.   string font_rootname = remove_suffix (basename (font_name));
  53.  
  54.   if (logging)
  55.     log_file = xfopen (extend_filename (font_rootname, "log"), "w");
  56.  
  57.   /* Initializing the display might involve forking a process.  We
  58.      wouldn't want that process to get copies of open output files,
  59.      since then when it exited, random stuff might get written to the
  60.      end of the file.  */
  61.   init_display (f);
  62.  
  63.   if (strlen (BITMAP_FONT_COMMENT (f)) > 0)
  64.     REPORT1 ("{%s}\n", BITMAP_FONT_COMMENT (f));
  65.  
  66.   if (output_name == NULL)
  67.     output_name = font_rootname;
  68.  
  69.   bzr_start_output (output_name, f);
  70.  
  71.   /* The main loop: for each character, find the outline of the shape,
  72.      then fit the splines to it.  */
  73.   for (code = starting_char; code <= ending_char; code++)
  74.     {
  75.       pixel_outline_list_type pixels;
  76.       spline_list_array_type splines;
  77.       char_info_type *c = get_char (font_name, code);
  78.     
  79.       if (c == NULL) continue;
  80.  
  81.       REPORT1 ("[%u ", code);
  82.       if (logging)
  83.     {
  84.       LOG ("\n\n\f");
  85.       print_char (log_file, *c);
  86.     }
  87.  
  88.       x_start_char (*c);
  89.       pixels = find_outline_pixels (*c);
  90.       /* `find_outline_pixels' uses corners as the coordinates, instead
  91.          of the pixel centers.  So we have to increase the bounding box.  */
  92.       CHAR_MIN_COL (*c)--; CHAR_MAX_COL (*c)++;
  93.       CHAR_MIN_ROW (*c)--; CHAR_MAX_ROW (*c)++;
  94.  
  95.       REPORT ("|");
  96.       splines = fitted_splines (pixels);
  97.  
  98.       bzr_output_char (*c, splines);
  99.       
  100.       /* Flush output before displaying the character, in case the user
  101.          is interested in looking at it and the online version
  102.          simultaneously.  */
  103.       flush_log_output ();
  104.  
  105.       x_output_char (*c, splines);
  106.       REPORT ("]\n");
  107.  
  108.       /* If the character was empty, it won't have a bitmap.  */
  109.       if (BITMAP_BITS (CHAR_BITMAP (*c)) != NULL)
  110.         free_bitmap (&CHAR_BITMAP (*c));
  111.  
  112.       free_pixel_outline_list (&pixels);
  113.       free_spline_list_array (&splines);
  114.     }
  115.  
  116.   bzr_finish_output ();
  117.   close_display ();
  118.  
  119.   close_font (font_name);
  120.  
  121.   return 0;
  122. }
  123.  
  124. /* Reading the options.  */
  125.  
  126. /* This is defined in version.c.  */
  127. extern string version_string;
  128.  
  129. #define USAGE "Options:
  130. <font_name> should be a filename, possibly with a resolution, e.g.,
  131.   `cmr10' or `cmr10.300'.\n"                        \
  132.   GETOPT_USAGE                                \
  133. "align-threshold <real>: if either coordinate of the endpoints on a
  134.   spline is closer than this, make them the same; default is .5.
  135. corner-always-threshold <angle-in-degrees>: if the angle at a pixel is
  136.   less than this, it is considered a corner, even if it is within
  137.   `corner-surround' pixels of another corner; default is 60.
  138. corner-surround <unsigned>: number of pixels on either side of a
  139.   point to consider when determining if that point is a corner; default
  140.   is 4.
  141. corner-threshold <angle-in-degrees>: if a pixel, its predecessor(s),
  142.   and its successor(s) meet at an angle smaller than this, it's a
  143.   corner; default is 100.
  144. display-continue: do not wait for you to hit return after displaying
  145.   each character.
  146. display-grid-size <unsigned>: number of expanded pixels between the grid
  147.   lines; default is 10. 
  148. display-pixel-size <unsigned>: length of one side of the square that
  149.   each pixel expands into; default is 9.
  150. display-rectangle-size <unsigned>: length of one side of the square
  151.   we draw to represent pixels; default is 6.  Must be less than
  152.   display-pixel-size. 
  153. do-display: show some information in a window, online.
  154. dpi <unsigned>: use a resolution of <unsigned>; default is 300.
  155. error-threshold <real>: subdivide fitted curves that are off by
  156.   more pixels than this; default is 2.0.
  157. filter-alternative-surround <unsigned>: another choice for
  158.   filter-surround; default is 1.
  159. filter-epsilon <real>: if the angles using filter-surround and
  160.    filter-alternative-surround points differ by more than this, use the
  161.    latter; default is 10.0.
  162. filter-iterations <unsigned>: smooth the curve this many times
  163.   before fitting; default is 4.
  164. filter-percent <percent>: when filtering, use the old point plus this
  165.   much of neighbors to determine the new point; default is 33.
  166. filter-surround <unsigned>: number of pixels on either side of a point
  167.   to consider when filtering that point; default is 2.
  168. help: print this message.
  169. keep-knees: do not remove ``knees''---points on the inside of the
  170.   outline that are between two others.
  171. line-reversion-threshold <real>: if a spline is closer to a straight
  172.    line than this, weighted by the square of the curve length, keep it a
  173.    straight line even if it is a list with curves; default is .01.
  174. line-threshold <real>: if the spline is not more than this far away
  175.   from the straight line defined by its endpoints, 
  176.   then output a straight line; default is 1.
  177. log: write detailed progress reports to <font_name>.log.
  178. output-file <filename>: write to <filename> if it has a suffix and to
  179.   `<filename>.bzr' if it doesn't.  Default is `<font_name>.bzr'.
  180. range <char1>-<char2>: only process characters between <char1> and
  181.   <char2>, inclusive. 
  182. reparameterize-improve <percent>: if reparameterization
  183.   doesn't improve the fit by this much, as a percentage, stop; default
  184.   is 10.
  185. reparameterize-threshold <real>: if an initial fit is off by more
  186.   pixels than this, don't bother to reparameterize; default is 30.
  187. subdivide-search <percent>: percentage of the curve from the initial
  188.   guess for a subdivision point to look for a better one; default is 10.
  189. subdivide-surround <unsigned>: number of points on either side of a
  190.   point to consider when looking for a subdivision point; default is 4.
  191. subdivide-threshold <real>: if a point is this close or closer to a
  192.   straight line, subdivide there; default is .03.
  193. tangent-surround <unsigned>: number of points on either side of a
  194.   point to consider when computing the tangent at that point; default is 3.
  195. verbose: print brief progress reports on stderr.
  196. version: print the version number of this program.
  197. "
  198.  
  199. /* We return the name of the font to process.  */
  200.  
  201. static string
  202. read_command_line (int argc, string argv[])
  203. {
  204.   int g;   /* `getopt' return code.  */
  205.   int option_index;
  206.   boolean explicit_dpi = false;
  207.   boolean printed_version = false;
  208.   struct option long_options[]
  209.     = { { "align-threshold",        1, 0, 0 },
  210.         { "corner-always-threshold",    1, 0, 0 },
  211.         { "corner-surround",            1, 0, 0 },
  212.         { "corner-threshold",           1, 0, 0 },
  213.         { "do-display",                 0, (int *) &wants_display, 1 },
  214.         { "display-continue",        0, (int *) &display_continue, 1 }, 
  215.         { "display-grid-size",        1, 0, 0 },
  216.         { "display-pixel-size",        1, 0, 0 },
  217.         { "display-rectangle-size",    1, 0, 0 },
  218.         { "dpi",                        1, (int *) &explicit_dpi, 1 },
  219.         { "error-threshold",            1, 0, 0 },
  220.         { "filter-alternative-surround",1, 0, 0 },
  221.         { "filter-epsilon",        1, 0, 0 },
  222.         { "filter-iterations",          1, 0, 0 },
  223.         { "filter-percent",        1, 0, 0 },
  224.         { "filter-secondary-surround",  1, 0, 0 },
  225.         { "filter-surround",            1, 0, 0 },
  226.         { "help",                       0, 0, 0 },
  227.         { "keep-knees",            0, (int *) &keep_knees, 1 },
  228.         { "line-reversion-threshold",    1, 0, 0 },
  229.         { "line-threshold",             1, 0, 0 },
  230.         { "log",                        0, (int *) &logging, 1 },
  231.         { "output-file",        1, 0, 0 },
  232.         { "range",                      1, 0, 0 },
  233.         { "reparameterize-improve",     1, 0, 0 },
  234.         { "reparameterize-threshold",   1, 0, 0 },
  235.         { "subdivide-search",        1, 0, 0 },
  236.         { "subdivide-surround",        1, 0, 0 },
  237.         { "subdivide-threshold",    1, 0, 0 },
  238.         { "tangent-surround",           1, 0, 0 },
  239.         { "verbose",                    0, (int *) &verbose, 1 },
  240.         { "version",                    0, (int *) &printed_version, 1 },
  241.         { 0, 0, 0, 0 } };
  242.  
  243.   while (true)
  244.     {
  245.       g = getopt_long_only (argc, argv, "", long_options, &option_index);
  246.       
  247.       if (g == EOF)
  248.         break;
  249.  
  250.       if (g == '?')
  251.         exit (1);  /* Unknown option.  */
  252.   
  253.       assert (g == 0); /* We have no short option names.  */
  254.       
  255.       if (ARGUMENT_IS ("align-threshold"))
  256.         align_threshold = atof (optarg);
  257.         
  258.       else if (ARGUMENT_IS ("corner-always-threshold"))
  259.         corner_always_threshold = atof (optarg);
  260.         
  261.       else if (ARGUMENT_IS ("corner-surround"))
  262.         corner_surround = atou (optarg);
  263.       
  264.       else if (ARGUMENT_IS ("corner-threshold"))
  265.         corner_threshold = atou (optarg);
  266.       
  267.       else if (ARGUMENT_IS ("display-grid-size"))
  268.         display_grid_size = atou (optarg);
  269.       
  270.       else if (ARGUMENT_IS ("display-pixel-size"))
  271.         display_pixel_size = atou (optarg);
  272.       
  273.       else if (ARGUMENT_IS ("display-rectangle-size"))
  274.         display_rectangle_size = atou (optarg);
  275.  
  276.       else if (ARGUMENT_IS ("dpi"))
  277.         dpi = optarg;
  278.       
  279.       else if (ARGUMENT_IS ("error-threshold"))
  280.         error_threshold = atof (optarg);
  281.       
  282.       else if (ARGUMENT_IS ("filter-alternative-surround"))
  283.         filter_alternative_surround = atou (optarg);
  284.       
  285.       else if (ARGUMENT_IS ("filter-epsilon"))
  286.         filter_epsilon = atof (optarg);
  287.         
  288.       else if (ARGUMENT_IS ("filter-iterations"))
  289.         filter_iteration_count = atou (optarg);
  290.  
  291.       else if (ARGUMENT_IS ("filter-percent"))
  292.         filter_percent = GET_PERCENT (optarg);
  293.  
  294.       else if (ARGUMENT_IS ("filter-surround"))
  295.         filter_surround = atou (optarg);
  296.  
  297.       else if (ARGUMENT_IS ("help"))
  298.         {
  299.           fprintf (stderr, "Usage: %s [options] <font_name>.\n", argv[0]);
  300.           fprintf (stderr, USAGE);
  301.           exit (0);
  302.         }
  303.  
  304.       else if (ARGUMENT_IS ("line-reversion-threshold"))
  305.         line_reversion_threshold = atof (optarg);
  306.         
  307.       else if (ARGUMENT_IS ("line-threshold"))
  308.         line_threshold = atof (optarg);
  309.       
  310.       else if (ARGUMENT_IS ("output-file"))
  311.         output_name = optarg;
  312.       
  313.       else if (ARGUMENT_IS ("range"))
  314.         GET_RANGE (optarg, starting_char, ending_char);
  315.       
  316.       else if (ARGUMENT_IS ("reparameterize-improve"))
  317.         reparameterize_improvement = GET_PERCENT (optarg);
  318.  
  319.       else if (ARGUMENT_IS ("reparameterize-threshold"))
  320.         reparameterize_threshold = atof (optarg);
  321.  
  322.       else if (ARGUMENT_IS ("subdivide-search"))
  323.         subdivide_search = GET_PERCENT (optarg);
  324.  
  325.       else if (ARGUMENT_IS ("subdivide-surround"))
  326.         subdivide_surround = atou (optarg);
  327.  
  328.       else if (ARGUMENT_IS ("subdivide-threshold"))
  329.         subdivide_threshold = atof (optarg); 
  330.  
  331.       else if (ARGUMENT_IS ("tangent-surround"))
  332.         tangent_surround = atou (optarg);
  333.  
  334.       else if (ARGUMENT_IS ("version"))
  335.         printf ("%s.\n", version_string);
  336.       
  337.       /* Else it was just a flag; getopt has already done the assignment.  */
  338.     }
  339.   
  340.   FINISH_COMMAND_LINE ();
  341. }
  342.